﻿// DEPENDENCIES:
//   Javascript
//   - jquery
//   - jquery.validate
//   - jquery.form
//   - jquery.metadata

using System;
using System.Data;
using System.Globalization;
using System.Web;
using System.Text;

namespace BigfootMVC.Helpers
{

    /// <summary>
    /// The HTML helper class aids in the raw ouput of html in your views. It has helpers
    /// to output input controls, and all other kind of select tags. This is done in a 
    /// fluid way sort of like jQuery by using the TagBuilder class as the return value of every mehtod
    /// once your are doing composing your html element you simple call ToString and the correctly ouputed 
    /// tag value is returned for inclusing in the view. It also has generic method for Html and Url encode 
    /// string as well as general purpose function for working with HTML.
    /// 
    /// It also has the smarts for dealing with issues like checkbox values not included the post when not checked 
    /// etc. It also makes it easy to create select elements with its options in a more programtically friendly way
    /// including the selection of the proper options when binding your ViewModel etc.
    /// 
    /// You can also use the TagBuilder class to create any HTML tag including the inclussion of Child tags. The HtmlHelper
    /// class however just creates shortcuts to to jumpstart the creation of common tags using the TagBuilder. They then
    /// return the TagBuilder class so you can continue to compose your html output.
    /// 
    /// The TagBuilder is an amazing class that allows you to build a whole field ouput including its label and 
    /// validation requirements in a single line of code.
    /// 
    /// For Example: <%=HtmlHelper.TextBox("Name").Value(123).Label("Amount").ValRequired()%>
    /// </summary>
    public class HtmlHelper
    {

        public HtmlHelper(){}

        public static HtmlHelper Create()
        {
            return new HtmlHelper();
        }

        /// <summary>
        /// Html encode some text
        /// </summary>
        /// <param name="data">The string to encode</param>
        /// <returns>The encoded string</returns>
        public string HtmlEncode(string data)
        {
            return HttpUtility.HtmlEncode(data);
        }

        /// <summary>
        /// Html decode some text
        /// </summary>
        /// <param name="data">The string to decode</param>
        /// <returns>The decoded string</returns>
        public string HtmlDecode(string data)
        {
            return HttpUtility.HtmlDecode(data);
        }

        /// <summary>
        /// Create html output from text by replacing the line feeds etc.
        /// </summary>
        /// <param name="data">The text data to convert</param>
        /// <returns>The Html output</returns>
        public string TextToHtml(string data)
        {
            var n = data;
            n = HtmlEncode(n);
            n = n.Replace("\r\n", "<br />");
            n = n.Replace("\n", "<br />");
            n = n.Replace("\r", "<br />");
            n = n.Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
            n = n.Replace(Environment.NewLine, "<br />");
            return n;
        }

        /// <summary>
        /// Outputs the start the form element declaration
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BeginForm()
        {
            return new TagBuilder("form", RenderMode.openTagOnly);
        }

        /// <summary>
        /// Outputs the start the form element declaration
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BeginForm(string id)
        {
            return new TagBuilder("form", RenderMode.openTagOnly).ID(id);
        }

        /// <summary>
        /// Outputs the end of the form element declaration
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string EndForm()
        {
            return "</form>";
        }

        /// <summary>
        /// Builds a Javascript Link tag
        /// </summary>
        /// <param name="filePath">The path to the javascrpt file</param>
        /// <returns>The html for the link element</returns>
        public string JSReference(string filePath)
        {
            return new TagBuilder("script").attr("type", "text/javascript").src(filePath).ToString();
        }

        /// <summary>
        /// Builds a CSS reference tag
        /// </summary>
        /// <param name="filePath">The path to the CSS file</param>
        /// <returns>The html for the CSS reference element</returns>
        public string CSSReference(string filePath)
        {
            return new TagBuilder("link").href(filePath).attr("rel", "stylesheet").attr("type", "text/css").ToString();
        }

        public string GoogleCDN_JQuery()
        {
            return "https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js";
        }

        public string GoogleCDN_JQueryUI()
        {
            return "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js";
        }

        public string GoogleCDN_JQueryUI_Theme(string themeName)
        {
            return "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/themes/" + themeName + "/jquery-ui.css";
        }

        ///// <summary>
        ///// Creates a reference to jQuery UI. If checkFirst is employed then it only adds it if version 1.8.7 is not already added.
        ///// Uses the CDN if specified.
        ///// </summary>
        ///// <param name="useCDN">Determines whether to use the CDN</param>
        ///// <param name="localFile">The local JS file in case you are not using the CDN</param>
        ///// <param name="theme">
        ///// If loading from the CDN the name of the theme (replace spaces in the name of the theme with dashes). 
        ///// If loading from local source the href of the css file.
        ///// </param>
        ///// <param name="useLocalTheme">Tells the system to use the local theme for jQuery.UI</param>
        ///// <param name="checkFirst">Checks if jQuery is loaded before it loads it</param>
        ///// <returns>A script</returns>
        //public string LoadJQueryUI(bool useCDN, string localFile, string theme, bool useLocalTheme, bool checkFirst)
        //{
        //    var src = useCDN ? "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js" 
        //                     : localFile;
        //    var themeHref = (useCDN && !useLocalTheme ) 
        //                           ? "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/themes/" + theme + "/jquery-ui.css" 
        //                           : theme;

        //    // Return a straight up reference if not checking first
        //    if (!checkFirst)
        //    {
        //        return JSReference(src) + "\r " + CSSReference(themeHref);
        //    }

        //    var script = new StringBuilder();
        //    script.Append("<script type='text/javascript'>");
        //    script.Append("if (typeof(jQuery.ui) == 'undefined' || jQuery.ui.version < '1.8.7') {");
        //    //script.Append("alert('loading jqueryui');");
        //    script.Append(CreateScriptToAddJSReference(src));
        //    script.Append(CreateScriptToAddCSSReference(themeHref));
        //    script.Append("}");
        //    script.Append("</script>");
        //    return script.ToString();
        //}

        ///// <summary>
        ///// Creates a reference to jQuery UI. Uses the CDN if specified.
        ///// </summary>
        ///// <param name="useCDN">Determines whether to use the CDN</param>
        ///// <param name="localFile">The local JS file in case you are not using the CDN</param>
        ///// <param name="theme">
        ///// If loading from the CDN the name of the theme (replace spaces in the name of the theme with dashes). 
        ///// If loading from local source the href of the css file.
        ///// </param>
        ///// <returns>A script</returns>
        //public string LoadJQueryUI(bool useCDN, string localFile, string theme)
        //{
        //    return LoadJQueryUI(useCDN, localFile, theme, !useCDN, false);
        //}


        ///// <summary>
        ///// Loads jQuery UI from Google's CDN
        ///// </summary>
        ///// <param name="theme">The theme to use.</param>
        ///// <param name="checkFirst">Determines whether to check of it is loaded before loading it</param>
        ///// <returns>A link to the script file or a script depending on whether check first is true</returns>
        //public string LoadJQueryUIFromCDN(string theme, bool checkFirst)
        //{
        //    return LoadJQueryUI(true, "", theme, false, checkFirst);
        //}

        ///// <summary>
        ///// Loads jQuery UI from Google's CDN with Smoothness as the theme
        ///// </summary>
        ///// <param name="checkFirst">Determines whether to check of it is loaded before loading it</param>
        ///// <returns>A link to the script file or a script depending on whether check first is true</returns>
        //public string LoadJQueryUIFromCDN(bool checkFirst)
        //{
        //    return LoadJQueryUI(true, "", "smoothness", false, checkFirst);
        //}

        ///// <summary>
        ///// Loads jQuery UI from Google's CDN with Smoothness as the theme
        ///// </summary>
        ///// <returns>A link to the script and css file</returns>
        //public string LoadJQueryUIFromCDN()
        //{
        //    return LoadJQueryUI(true, "", "smoothness", false, false);
        //}

        ///// <summary>
        ///// Loads jQuery UI from the local store
        ///// </summary>
        ///// <param name="src">The local jquery js file</param>
        ///// <param name="themeCSSHref">The href to the css file for the theme</param>
        ///// <returns>A link to the script file or a script depending on whether check first is true</returns>
        //public string LoadJQueryUILocal(string src, string themeCSSHref)
        //{
        //    return LoadJQueryUI(false, src, themeCSSHref, true, false);
        //}

        ///// <summary>
        ///// Loads jQuery UI from the local store
        ///// </summary>
        ///// <param name="src">The source of the javascript file</param>
        ///// <param name="themeCSSHref">The href to the css file for the theme</param>
        ///// <param name="checkFirst">Determines whether to check of it is loaded before loading it</param>
        ///// <returns>A link to the script file or a script depending on whether check first is true</returns>
        //public string LoadJQueryUILocal(string src, string themeCSSHref, bool checkFirst)
        //{
        //    return LoadJQueryUI(false, src, themeCSSHref, true, checkFirst);
        //}

        ///// <summary>
        ///// Add a reference to bigfootMVC. If checkFirst is employed then it only adds it if 
        ///// bigfootMVC is not already loaded or is less than 1.0.0
        ///// </summary>
        ///// <param name="src">The location of the local file.</param>
        ///// <returns>A script</returns>
        //public string LoadBigfootMVCScript(string src)
        //{
        //    return LoadBigfootMVCScript(src, false);
        //}

        ///// <summary>
        ///// Add a reference to bigfootMVC. If checkFirst is employed then it only adds it if 
        ///// bigfootMVC is not already loaded or is less than 1.0.0
        ///// </summary>
        ///// <param name="src">The location of the local file.</param>
        ///// <param name="checkFirst">Checks if bigfootMVC is loaded before it loads it</param>
        ///// <returns>A script</returns>
        //public string LoadBigfootMVCScript(string src, bool checkFirst)
        //{
        //    // Return a straight up reference if not checking first
        //    if (!checkFirst) return JSReference(src);

        //    var script = new StringBuilder();
        //    script.Append("<script type='text/javascript'>");
        //    script.Append("if (typeof (bigfootMVC) == 'undefined' || bigfootMVC.version < '1.0.0') {");
        //    //script.Append("alert('loading bigfootmvc');");
        //    script.Append(CreateScriptToAddJSReference(src));
        //    script.Append("}");
        //    script.Append("</script>");
        //    return script.ToString();
        //}

        ///// <summary>
        ///// Creates the script necessary to insert a script reference into the head of the document
        ///// </summary>
        ///// <param name="src">The source of the script file</param>
        //private string CreateScriptToAddJSReference(string src)
        //{
        //    var script = new StringBuilder();
        //    script.Append("    var fileref=document.createElement('script');");
        //    script.Append("    fileref.setAttribute('type','text/javascript');");
        //    script.Append("    fileref.setAttribute('src', '" + src + "');");
        //    script.Append("    document.getElementsByTagName('head')[0].appendChild(fileref);");
        //    return script.ToString();
        //}

        ///// <summary>
        ///// Creates the script necessary to insert a script reference into the head of the document
        ///// </summary>
        ///// <param name="href">The source of the CSS file to reference</param>
        //private string CreateScriptToAddCSSReference(string href)
        //{
        //    var script = new StringBuilder();
        //    script.Append("    var fileref=document.createElement('link');");
        //    script.Append("    fileref.setAttribute('rel', 'stylesheet');");
        //    script.Append("    fileref.setAttribute('type', 'text/css');");
        //    script.Append("    fileref.setAttribute('href', '" + href + "');");
        //    script.Append("    document.getElementsByTagName('head')[0].appendChild(fileref);");
        //    return script.ToString();
        //}
        
        /// <summary>
        /// Create a div tag
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder DIV()
        {
            return new TagBuilder("div");
        }

        /// <summary>
        /// Creates a div tag and oupts the content provided as the innner html
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder DIV(string content)
        {
            return new TagBuilder("div").InnerHtml(content);
        }

        /// <summary>
        /// Creates a div tag and oupts the content provided as the innner html
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder DIV(string content, string classes)
        {
            return new TagBuilder("div").InnerHtml(content).AddClass(classes);
        }

        /// <summary>
        /// Create a span element
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder SPAN()
        {
            return new TagBuilder("span");
        }

        /// <summary>
        /// Creates a span element including the contnet to include the inner html
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder SPAN(string content)
        {
            return new TagBuilder("span").InnerHtml(content);
        }

        /// <summary>
        /// Creates a span element including the contnet to include the inner html
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder SPAN(string content, string classes)
        {
            return new TagBuilder("span").InnerHtml(content).AddClass(classes);
        }

        /// <summary>
        /// Creates a textbox input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder TextBox(string name)
        {
            return new TagBuilder("input").IDandName(name).type("text");
        }

        /// <summary>
        /// Creates a textbox input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundTextBox(string name)
        {
            return new TagBuilder("input").IDandName(name).type("text").bindValue(name);
        }

        /// <summary>
        /// Creates a textbox input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name</param>
        /// <param name="id">The id for this element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder TextBox(string name, string id)
        {
            return new TagBuilder("input").ID(id).Name(name).type("text");
        }

        public string DisplayError(string error)
        {
            return DisplayError(error, "");
        }

        public string DisplayError(string error, string classNames)
        {
            return !string.IsNullOrEmpty(error) 
                    ? new TagBuilder("span").InnerText(error).AddClass("error " + classNames).ToString()
                    : "";
        }

        /// <summary>
        /// Creates a file input
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder File()
        {
            return new TagBuilder("input").type("file");
        }

        /// <summary>
        /// Creates a file input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder File(string name)
        {
            return new TagBuilder("input").IDandName(name).type("file");
        }

        /// <summary>
        /// Creates a file input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name</param>
        /// <param name="id">The id for this element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder File(string name, string id)
        {
            return new TagBuilder("input").Name(name).ID(id).type("file");
        }

        /// <summary>
        /// Creates a password input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Password(string name)
        {
            return new TagBuilder("input").IDandName(name).type("password");
        }

        /// <summary>
        /// Creates a textarea input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder TextArea(string name)
        {
            return new TagBuilder("textarea").IDandName(name);
        }

        /// <summary>
        /// Creates a textarea input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name</param>
        /// <param name="id">The id to assign to the element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder TextArea(string name, string id)
        {
            return new TagBuilder("textarea").Name(name).ID(id);
        }

        /// <summary>
        /// Creates a hidden input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Hidden(string name)
        {
            return new TagBuilder("input").IDandName(name).type("hidden");
        }

        /// <summary>
        /// Creates a hidden input
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="id">The id to assign</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Hidden(string name, string id)
        {
            return new TagBuilder("input").Name(name).ID(id).type("hidden");
        }

        /// <summary>
        /// Creates a button input
        /// </summary>
        /// <param name="text">The text to include in the button</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Button(string text)
        {
            return new TagBuilder("button").InnerText(text);
        }

        /// <summary>
        /// Creates a label for a certain input. You can also alternatively use the .label method on the tagbuilder to add a label to 
        /// an input control while creating the control. The fieldLabel css class is assigned to the label for ease of targeting when formatting.
        /// </summary>
        /// <param name="forName">The input the label belongs to</param>
        /// <param name="labelText">The text to print for the label</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Label(string forName, string labelText)
        {
            return Label(forName, labelText, true);
        }

        /// <summary>
        /// Creates a label for a certain input. You can also alternatively use the .label method on the tagbuilder to add a label to 
        /// an input control while creating the control. The fieldLabel css class is assigned to the label for ease of targeting when formatting.
        /// </summary>
        /// <param name="forName">The input the label belongs to</param>
        /// <param name="labelText">The text to print for the label</param>
        /// <param name="addFieldLabelClass">Determines wheather to add the fieldLabel css class to the label</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Label(string forName, string labelText, bool addFieldLabelClass)
        {
            return new TagBuilder("label").@for(forName).InnerText(labelText).AddClassIf(addFieldLabelClass, "fieldLabel");
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="value">The value of the checkbox</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, bool value)
        {
            return Checkbox(name, value, string.Empty, string.Empty);
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="value">The value of the checkbox</param>
        /// <param name="cssclass">The CSS class to assign to the checkbox</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, bool value, string cssclass)
        {
            return Checkbox(name, value, cssclass, string.Empty);
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="value">The value of the checkbox</param>
        /// <param name="cssclass">The CSS class to assign to the checkbox</param>
        /// <param name="label">The label to include the checkbox</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, bool value, string cssclass, string label)
        {
            return Checkbox(name, name, value, cssclass, label, "", 0);
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="value">The value of the checkbox</param>
        /// <param name="cssclass">The CSS class to assign to the checkbox</param>
        /// <param name="label">The label to include the checkbox</param>
        /// <param name="labelCssClass">The CSS class to assign to the label</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, bool value, string cssclass, string label, string labelCssClass)
        {
            return Checkbox(name, name, value, cssclass, label, labelCssClass, 0);
        }

        public string Checkbox(string name, bool value, string cssclass, string label, string labelCssClass, int tabIndex)
        {
            return Checkbox(name, name, value, cssclass, label, labelCssClass, tabIndex);
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="id">The ID to assign to the element</param>
        /// <param name="value">The value of the checkbox</param>
        /// <param name="cssclass">The CSS class to assign to the checkbox</param>
        /// <param name="label">The label to include the checkbox</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, string id, bool value, string cssclass, string label)
        {
            return Checkbox(name, id, value, cssclass, label, "", 0);
        }

        /// <summary>
        /// Creates a checkbox input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="id">The ID to assign to the element</param>
        /// <param name="value">The value of the checkbox</param>
        /// <param name="cssclass">The CSS class to assign to the checkbox</param>
        /// <param name="label">The label to include the checkbox</param>
        /// <param name="labelCssClass">The CSS class to assign to the label</param>
        /// <param name="tabIndex">The tabIndex if any to assign to the checkbox</param>
        /// <returns>A string with the html for the checkbox</returns>
        public string Checkbox(string name, string id, bool value, string cssclass, string label, string labelCssClass, int tabIndex)
        {
            var chkname = name + "_chk";
            var chkid = id + "_chk";
            var chk = new TagBuilder("input").Name(chkname).ID(chkid).type("checkbox");
            var hdn = new TagBuilder("input").Name(name).ID(id).type("hidden");
            // Figure out the value
            if (value)
            {
                chk.@checked(true);
                hdn.value("true");
            }
            else
            {
                chk.@checked(false);
                hdn.value("false");
            }
            // Add the label
            if (string.IsNullOrEmpty(label) == false)
            {
                if (!string.IsNullOrEmpty(labelCssClass))
                    chk.Label(label, labelCssClass);
                else
                    chk.Label(label);
            }
            // Add the class if asked
            if (string.IsNullOrEmpty(cssclass) == false)
            {
                chk.AddClass(cssclass);
            }
            if (tabIndex != 0)
            {
                chk.tabIndex(tabIndex);
            }
             // Wireup events
            chk.onclick("jQuery('#" + id + "').val(this.checked);");
            // Return the value
            return chk.ToString() + hdn;
        }
        
        /// <summary>
        /// Creates a radio input. It correctly deals with the issue related to the false value of a checkbox not being sent to the client 
        /// </summary>
        /// <param name="name">The value to assign to the input as the name and id</param>
        /// <param name="value">The value of the checkbox</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Radio(string name, string value)
        {
            return new TagBuilder("input").type("radio").Name(name).value(value);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundRadioList(string name, SelectItemList items)
        {
            return BoundRadioList(name, items.ToArray(), -1);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundRadioList(string name, SelectItem[] items)
        {
            return BoundRadioList(name, items, -1);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <param name="tabIndex">The tabIndex to assign to the radio item</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundRadioList(string name, SelectItemList items, int tabIndex)
        {
            return BoundRadioList(name, items.ToArray(), tabIndex);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <param name="tabIndex">The tabIndex to assign to the radio item</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundRadioList(string name, SelectItem[] items, int tabIndex)
        {
            var parent = new TagBuilder("span").ID(name + "Container");

            var i = 0;
            foreach (var item in items)
            {

                // Add radioItem
                var radioItem = parent.AddChild("span").AddClass("radioItem");

                // Add the radio input
                var radio = radioItem.AddChild("input").Name(name).type("radio").value(item.Value).ID(name + i).bindChecked(name);
                
                // Set the tabIndex
                if (tabIndex > -1) radio.tabIndex(tabIndex);

                // Add the radio label
                radioItem.AddChild("label").@for(name + i).AddClass("radioLabel").InnerText(item.Text);

                // Make the id unique
                i += 1;
            }

            return parent;
        }

        /// <summary>
        /// Create a radio list where the value is meant to be a boolean value.
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="value">True or false. These string value will be translated to true: on, yes, true, 1 as needed to identify as true</param>
        /// <param name="items">Option list</param>
        public TagBuilder RadioList(string name, bool value, SelectItemList items)
        {
            foreach (SelectItem item in items.ToArray()) {
                var itemBoolValue = false;
                switch (item.Value.ToLower()) {
                    case "on":
                        itemBoolValue = true;
                        break;
                    case "yes":
                        itemBoolValue = true;
                        break;
                    case "true":
                        itemBoolValue = true;
                        break;
                    case "1":
                        itemBoolValue = true;
                        break;
                }
                item.Selected = (itemBoolValue == value);
            }
            return RadioList(name, items);
        }

        /// <summary>
        /// Create a radio list where the value is meant to be a string.
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="value">True or false. These string value will be translated to true: on, yes, true, 1 as needed to identify as true</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, string value, SelectItemList items)
        {
            return RadioList(name, value, items.ToArray());
        }

        /// <summary>
        /// Create a radio list where the value is meant to be a string.
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="value">True or false. These string value will be translated to true: on, yes, true, 1 as needed to identify as true</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, string value, SelectItem[] items)
        {
            if (string.IsNullOrEmpty(value) == false) {
                foreach (var item in items) {
                    if (item.Value.ToLower() == value.ToLower())
                        item.Selected = true;
                }
            }
            return RadioList(name, items);
        }

        /// <summary>
        /// Create a radio list where the value is meant to be a string.
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="value">True or false. These string value will be translated to true: on, yes, true, 1 as needed to identify as true</param>
        /// <param name="items">Option list</param>
        /// <param name="tabIndex">The tab index to assign to the radio item</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, string value, SelectItemList items, int tabIndex)
        {
            if (string.IsNullOrEmpty(value) == false)
            {
                foreach (var item in items.ToArray())
                {
                    if (item.Value.ToLower() == value.ToLower())
                        item.Selected = true;

                }
            }
            return RadioList(name, items, tabIndex);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, SelectItemList items)
        {
            return RadioList(name, items, -1);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, SelectItem[] items)
        {
            return RadioList(name, items, -1);
        }

        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <param name="tabIndex">The tabIndex to assign to the radio item</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, SelectItem[] items, int tabIndex)
        {

            return RadioList(name, new SelectItemList(items), tabIndex);
        }
        
        /// <summary>
        /// Create a radio list
        /// </summary>
        /// <param name="name">Element Name</param>
        /// <param name="items">Option list</param>
        /// <param name="tabIndex">The tabIndex to assign to the radio item</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder RadioList(string name, SelectItemList items, int tabIndex)
        {
            var parent = new TagBuilder("span").ID(name + "Container");

            var i = 0;
            foreach (var item in items.ToArray()) {

                // Add radioItem
                var radioItem = parent.AddChild("span").AddClass("radioItem");

                // Add the radio input
                var radio = radioItem.AddChild("input").Name(name).type("radio").value(item.Value).ID(name + i);
                // Mark as selected
                if (item.Selected)
                    radio.@checked(true);

                // Set the tabIndex
                if (tabIndex > -1) radio.tabIndex(tabIndex);

                // Add the radio label
                radioItem.AddChild("label").@for(name + i).AddClass("radioLabel").InnerText(item.Text);

                // Make the id unique
                i += 1;
            }

            return parent;
        }

        /// <summary>
        /// Create a bound select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundSelect(string name)
        {
            return new TagBuilder("select").IDandName(name).bindValue(name);
        }

        /// <summary>
        /// Create a bound select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The javascript array containing the options to bind to the select list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundSelect(string name, string options)
        {
            return new TagBuilder("select").IDandName(name).bindValue(name).bindOptions(options);
        }

        /// <summary>
        /// Create a bound select list. It is assumed that the source will be an Array of SelectItem(s). The optionsText is set to "Text" and the optionsValue is to "Value"
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The javascript array containing the options to bind to the select list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundSelectToSelectItems(string name, string options)
        {
            return new TagBuilder("select").IDandName(name).bindValue(name).bindOptions(options, "Text", "Value");
        }

        /// <summary>
        /// Create a bound select list. It is assumed that the source will be an Array of SelectItem(s). The optionsText is set to "Text" and the optionsValue is to "Value"
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The javascript array containing the options to bind to the select list</param>
        /// <param name="optionsCaption">The caption to display as selected the select box is null</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundSelectToSelectItems(string name, string options, string optionsCaption)
        {
            return new TagBuilder("select").IDandName(name).bindValue(name).bindOptions(options, "Text", "Value", optionsCaption);
        }

        /// <summary>
        /// Create a bound select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The javascript array containing the options to bind to the select list</param>
        /// <param name="optionsText">The property in the array to bind the option text to</param>
        /// <param name="optionsValue">The property in the array to bind the option value to</param>
        /// <param name="optionsCaption">The caption to display as selected the select box is null</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundSelect(string name, string options, string optionsText, string optionsValue, string optionsCaption)
        {
            return new TagBuilder("select").IDandName(name).bindValue(name).bindOptions(options, optionsText, optionsValue, optionsCaption);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name)
        {
            return new TagBuilder("select").IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="name">Name of the html element</param>
        /// <param name="id">Element ID</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, string id)
        {
            return new TagBuilder("select").Name(name).ID(id);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, SelectItem[] options)
        {
            return new TagBuilder("select").options(options).IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, SelectItemList options)
        {
            return new TagBuilder("select").options(options.ToArray()).IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="name">Name of the html element</param>
        /// <param name="id">Element ID</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, string id, SelectItem[] options)
        {
            return new TagBuilder("select").options(options).Name(name).ID(id);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="value">The selected value for the list</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, SelectItem[] options, object value)
        {
            return new TagBuilder("select").options(options, value).IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="value">The selected value for the list</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, SelectItem[] options, int value)
        {
            return new TagBuilder("select").options(options, value).IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="value">The selected value for the list</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <param name="name">Name use for the id and name of the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, SelectItem[] options, string value)
        {
            return new TagBuilder("select").options(options, value).IDandName(name);
        }

        /// <summary>
        /// Create a select list
        /// </summary>
        /// <param name="id">The ID to assign to the element</param>
        /// <param name="value">The selected value for the list</param>
        /// <param name="options">The list of options to add to the select list</param>
        /// <param name="name">Name use for the html element</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Select(string name, string id, SelectItem[] options, object value)
        {
            return new TagBuilder("select").options(options, value).Name(name).ID(id);
        }

        /// <summary>
        /// Create an anchor tag
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Link()
        {
            return new TagBuilder("a").href("javascript:void(0);");
        }

        /// <summary>
        /// Create an anchor tag
        /// </summary>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder BoundLink(string text, string clickCallback)
        {
            return new TagBuilder("a").href("javascript:void(0);").text(text).bindClick(clickCallback);
        }
        
        /// <summary>
        /// Create an anchor tag
        /// </summary>
        /// <param name="LinkText">The text to use for the link</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Link(string LinkText)
        {
            return new TagBuilder("a").InnerText(LinkText).href("javascript:void(0);");
        }

        /// <summary>
        /// Create an anchor tag that is absolutely positioned over a certain element in the html and is used as 
        /// box if you will around a certain image, block etc.
        /// </summary>
        /// <param name="Title">This is the caption that comes up when you mouse over the link</param>
        /// <param name="top">Distance from the top of the parent element</param>
        /// <param name="left">Distance from the left of the parent element</param>
        /// <param name="height">The height of the link area to cover in case of an image the height of the image</param>
        /// <param name="width">The width of the link area to cover in case of an image the width of the image</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder LinkOver(string Title, int top, int left, int width, int height)
        {
            return new TagBuilder("a").title(Title).href("javascript:void(0);").absolute(top, left).size(width, height);
        }

        public TagBuilder LinkOverSpriteOnHover(string Title, int top, int left, int width, int height, string hoverSpriteImage, string spritePosition)
        {
            return new TagBuilder("a").title(Title).href("javascript:void(0);").absolute(top, left).size(width, height)
                                      .showSpriteOnMouseOver(hoverSpriteImage, spritePosition);
        }

        public TagBuilder LinkOverSpriteOnHover(string Title, string hoverSpriteImage, string spritePosition)
        {
            return LinkOverSpriteOnHover(Title, hoverSpriteImage, spritePosition, false);
        }

        public TagBuilder LinkOverSpriteOnHover(string Title, string hoverSpriteImage, string spritePosition, bool debug)
        {
            return new TagBuilder("a").title(Title).href("javascript:void(0);").showSpriteOnMouseOver(hoverSpriteImage, spritePosition, debug);
        }
        
        /// <summary>
        /// Creates an anchor tag. This link does not have text, instead it uses as the background a sprite image
        /// </summary>
        /// <param name="Title">This is the caption that comes up when you mouse over the link</param>
        /// <param name="img">The sprite image</param>
        /// <param name="bgposition">The x y coordinate of the image in the sprite</param>
        /// <param name="width">The width of the sprite image used for this link</param>
        /// <param name="height">The height of the sprite image used for this link</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder LinkSprite(string Title, string img, string bgposition, int width, int height)
        {
            return new TagBuilder("a").title(Title).href("javascript:void(0);").sprite(img, bgposition, width, height).inlineblock();
        }

        /// <summary>
        /// Creates an anchor tag. This link does not have text, instead it uses as the background a sprite image. It also has
        /// a rolloever effect with another section of the sprite image. The rollover image site must be the same size
        /// </summary>
        /// <param name="Title">This is the caption that comes up when you mouse over the link</param>
        /// <param name="img">The sprite image</param>
        /// <param name="bgposition">The x y coordinate of the image in the sprite</param>
        /// <param name="width">The width of the sprite image used for this link</param>
        /// <param name="height">The height of the sprite image used for this link</param>
        /// <param name="rolloverposition">The x y coordinate of the image in the sprite for the rollover.</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder LinkSpriteRollover(string Title, string img, string bgposition, int width, int height, string rolloverposition)
        {
            return new TagBuilder("a").title(Title).href("javascript:void(0);").spriteRollover(img, bgposition, width, height, rolloverposition).inlineblock();
        }

        /// <summary>
        /// Creates an anchor tag. This link does not have text, instead it uses as the background a sprite image. It acts as a toggle using a sprite.
        /// </summary>
        /// <param name="Title">This is the caption that comes up when you mouse over the link</param>
        /// <param name="img">The sprite image</param>
        /// <param name="onPosition">The x y coordinate of the image in the sprite for the on state</param>
        /// <param name="offPosition">The x y coordinate of the image in the sprite for off state</param>
        /// <param name="isOn">Determines whether to show the on state by default</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder LinkToggleSprite(string Title, string img, string onPosition, string offPosition, bool isOn)
        {
            return LinkToggleSprite(Title, img, onPosition, offPosition, isOn, "", "");
        }

        /// <summary>
        /// Creates an anchor tag. This link does not have text, instead it uses as the background a sprite image. It acts as a toggle using a sprite.
        /// </summary>
        /// <param name="Title">This is the caption that comes up when you mouse over the link</param>
        /// <param name="img">The sprite image</param>
        /// <param name="onPosition">The x y coordinate of the image in the sprite for the on state</param>
        /// <param name="offPosition">The x y coordinate of the image in the sprite for off state</param>
        /// <param name="isOn">Determines whether to show the on state by default</param>
        /// <param name="onClickScript">The code to execute to toggle on</param>
        /// <param name="offClickScript">The code to execute to toggle off</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder LinkToggleSprite(string Title, string img, string onPosition, string offPosition, bool isOn, string onClickScript, string offClickScript)
        {
            if (!onClickScript.Trim().EndsWith(";")) onClickScript += ";";
            if (!offClickScript.Trim().EndsWith(";")) offClickScript += ";";
            return new TagBuilder("a").title(Title).href("javascript:void(0);")
                                      .attr("onPosition", onPosition)
                                      .attr("offPosition", offPosition)
                                      .attr("currentState", isOn ? "on" : "off")
                                      .addStyle("background-image: url('" + img + "')")
                                      .addStyle("background-position: " + (isOn ? onPosition : offPosition))
                                      .onmouseover("var $this = jQuery(this); " +
                                                   "var hoverPosition = $this.attr('currentState') == 'on' ? $this.attr('offPosition') : $this.attr('onPosition'); " +
                                                   /*"alert('mouseover: ' + hoverPosition);" +*/
                                                   "$this.css('background-position', hoverPosition);")
                                      .onmouseout( "var $this = jQuery(this); " +
                                                   "var hoverPosition = $this.attr('currentState') == 'on' ? $this.attr('onPosition') : $this.attr('offPosition'); " +
                                                   /*"alert('mouseout: ' + hoverPosition);" +*/
                                                   "$this.css('background-position', hoverPosition);")
                                      .onclick("var $this = jQuery(this); " +
                                               "var hoverPosition = $this.attr('currentState') == 'on' ? $this.attr('offPosition') : $this.attr('onPosition'); " +
                                               "$this.css('background-position', hoverPosition); " +
                                               "if ($this.attr('currentState') == 'on') " +
                                               "    { " + offClickScript + " $this.attr('currentState', 'off'); }" +
                                               "else " + 
                                               "    { " + onClickScript + " $this.attr('currentState', 'on'); }");
        }

        /// <summary>
        /// Creates an anchor tag that surrounds two divs that can be floated together to form the sliding door technique.
        /// </summary>
        /// <param name="Title">This is the text that will appear inside the link</param>
        /// <param name="leftCSSClass">This is the CSS class assigned to the left part of the sliding door technique</param>
        /// <param name="rightCSSClass">This is the CSS class assigned to the right part of the sliding door technique</param>        
        public TagBuilder LinkWithSlidingDoor(string Title, string leftCSSClass, string rightCSSClass)
        {
            var tb = new TagBuilder("a").href("javascript:void(0);");
            
            tb.AddChild("div").text(Title).AddClass(leftCSSClass)
                .Parent
              .AddChild("div").AddClass(rightCSSClass);

            return tb;

        }


        /// <summary>
        /// Create an anchor tag
        /// </summary>
        /// <param name="LinkText">The text to use for the link</param>
        /// <param name="href">The url to use for the link</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Link(string LinkText, string href)
        {
            return string.IsNullOrEmpty(href) ? Link(LinkText) : new TagBuilder("a").InnerText(LinkText).href(href);
        }

        /// <summary>
        /// Create an image tag
        /// </summary>
        /// <param name="src">Pass in the url to the image tag</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder Image(string src)
        {
            return new TagBuilder("img").src(src);
        }

        /// <summary>
        /// Creates an image tag using a sprite image as the background. To accomplish this it uses a blank image as the src for the image
        /// and it sets the background of the image element to be the xy coordinate of the right image in the sprite
        /// </summary>
        /// <param name="spriteImageUrl">The sprite image</param>
        /// <param name="bgposition">The x y coordinate of the image in the sprite</param>
        /// <param name="width">The width of the sprite image used for this link</param>
        /// <param name="height">The height of the sprite image used for this link</param>
        /// <param name="blankImageUrl">The blank image to use as the source</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageSprite(string spriteImageUrl, string bgposition, int width, int height, string blankImageUrl)
        {
            return new TagBuilder("img").src(blankImageUrl).sprite(spriteImageUrl, bgposition, width, height);
        }

        /// <summary>
        /// Creates an image tag using a sprite image as the background. To accomplish this it uses a blank image as the src for the image
        /// and it sets the background of the image element to be the xy coordinate of the right image in the sprite. It also adds
        /// a rollover effect to another xy coordinate in the sprite image where the rollover image is. The rolloever image in the sprite
        /// must be the same size as the original image
        /// </summary>
        /// <param name="spriteImageUrl">The sprite image</param>
        /// <param name="bgposition">The x y coordinate of the image in the sprite</param>
        /// <param name="width">The width of the sprite image used for this link</param>
        /// <param name="height">The height of the sprite image used for this link</param>
        /// <param name="rolloverposition">The x y coordinate of the image in the sprite to use for the rollover.</param>
        /// <param name="blankImageUrl">The blank image to use as the source</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageSpriteRollover(string spriteImageUrl, string bgposition, int width, int height, string rolloverposition, string blankImageUrl)
        {
            return new TagBuilder(blankImageUrl).src("blank.png").spriteRollover(spriteImageUrl, bgposition, width, height, rolloverposition);
        }

        /// <summary>
        /// Create an image tag with a rollover image effect
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="hoversrc">The url of the image to change to when the mouse rolls over the image</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageHover(string src, string hoversrc)
        {
            var setsrcscript = "this.src='{0}'";
            return new TagBuilder("img").src(src).onmouseover(string.Format(setsrcscript, hoversrc)).onmouseout(string.Format(setsrcscript, src));
        }

        

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag.
        /// </summary>
        /// <param name="src">The source of the image to use</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageLink(string src)
        {
            var lnk = new TagBuilder("a").href("javascript:void(0);").AddClass("pointer");
            lnk.AddChild("img").src(src).AddClass("pointer");
            return lnk;
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag.
        /// </summary>
        /// <param name="src">The source of the image to use</param>
        /// <param name="url">The url to assign to the anchor tag</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string ImageLink(string src, string url)
        {
            return ImageLink(src, url, "");
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag.
        /// </summary>
        /// <param name="src">The source of the image to use</param>
        /// <param name="url">The url to assign to the anchor tag</param>
        /// <param name="alt">Assign this alt text to the image</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string ImageLink(string src, string url, string alt)
        {
            return new TagBuilder("a").href(url).InnerHtml(Image(src).Alt(alt).ToString()).ToString();
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag that also displays some text in it
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="text">The text to display inside the image</param>
        /// <param name="textTop">The top position of the text relative to the image dimensions</param>
        /// <param name="textLeft">The left position of the text relative to the image dimensions</param>
        /// <param name="textClass">The classes to be applied to the span containing the text</param>
        /// <param name="linkClass">Assigns this class to the link class</param>
        /// <param name="imgClass">Assigns this class to the image class</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageLinkWithText(string src, string text, int textTop, int textLeft, string textClass, string linkClass, string imgClass)
        {
            var tag = (new TagBuilder("a"))
                        .href("javascript:void(0);").AddClass(linkClass)
                        .addStyle("position: relative; display: inline-block; text-decoration: none;")
                        .AddChild("span").text(text).absolute(textTop, textLeft).AddClass(textClass).addStyle("cursor: pointer;")
                        .Parent
                        .AddChild("img").src(src).AddClass(imgClass)
                        .Parent;
            return tag;
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag with a rollover effect.
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="hoversrc">The source of the image to use as the hover state</param>
        /// <param name="url">The url to assign to the anchor tag</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string ImageLinkHover(string src, string hoversrc, string url)
        {
            return ImageLinkHover(src, hoversrc, url, "");
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag with a rollover effect.
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="hoversrc">The source of the image to use as the hover state</param>
        /// <param name="url">The url to assign to the anchor tag</param>
        /// <param name="alt">Assign this alt text to the image</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string ImageLinkHover(string src, string hoversrc, string url, string alt)
        {
            return ImageLinkHover(src, hoversrc, url, alt, false);
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag with a rollover effect.
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="hoversrc">The source of the image to use as the hover state</param>
        /// <param name="url">The url to assign to the anchor tag</param>
        /// <param name="alt">Assign this alt text to the image</param>
        /// <param name="newWindow">Determine whether to open the link in a new window</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public string ImageLinkHover(string src, string hoversrc, string url, string alt, bool newWindow)
        {
            var tb = new TagBuilder("a").href(url).inlineblock().InnerHtml(ImageHover(src, hoversrc).Alt(alt).ToString());
            if (newWindow)
                tb.Target_Blank();
            return tb.ToString();
        }

        /// <summary>
        /// Create an image tag sorrounded by an anchor tag with a rollover effect that also displays some text in it
        /// </summary>
        /// <param name="src">The source of the image to use as the default state</param>
        /// <param name="hoversrc">The url of the image to change to when the mouse rolls over the image</param>
        /// <param name="text">The text to display inside the image</param>
        /// <param name="textTop">The top position of the text relative to the image dimensions</param>
        /// <param name="textLeft">The left position of the text relative to the image dimensions</param>
        /// <param name="textClass">The classes to be applied to the span containing the text</param>
        ///  <param name="linkClass">Assigns this class to the link class</param>
        /// <param name="imgClass">Assigns this class to the image class</param>
        /// <returns>A TagBuilder class to continue to create the tag by adding attr classes etc.</returns>
        public TagBuilder ImageLinkHoverWithText(string src, string hoversrc, string text, int textTop, int textLeft, string textClass, string linkClass, string imgClass)
        {
            var tag = (new TagBuilder("a"))
                        .href("javascript:void(0);")
                        .addStyle("position: relative; display: inline-block; text-decoration: none;").AddClass(linkClass)
                        .AddChild("span").text(text).absolute(textTop, textLeft).AddClass(textClass)
                            .addStyle("cursor: pointer;")
                            .onmouseover("jQuery(this).next().attr('src', '" + hoversrc + "')")
                            .onmouseout(" jQuery(this).next().attr('src', '" + src + "')")
                        .Parent
                        .AddChild("img").src(src).onmouseover("this.src='" + hoversrc + "'").onmouseout("this.src='" + src + "'").AddClass(imgClass)
                        .Parent;
            return tag;
        }

        /// <summary>
        /// Renders the content only if the speicfied condition is true
        /// </summary>
        /// <param name="condition">The condition that determines weather to render or not. If true it renders</param>
        /// <param name="content">The content to be redered</param>
        /// <returns>A RenderIfBuilder so that you may continue to build your conditional render statement with else etc.</returns>
        public RenderIfBuilder RenderIf(bool condition, string content)
        {
            return new RenderIfBuilder(condition, content);
        }

        /// <summary>
        /// Renders the content only if the speicfied condition is true
        /// </summary>
        /// <param name="condition">The condition that determines weather to render or not. If true it renders</param>
        /// <param name="format">The format to be merged with the supplied value used in the String.Format call</param>
        /// <param name="values">The values to be used in the String.Format call</param>
        /// <returns>A RenderIfBuilder so that you may continue to build your conditional render statement with else etc.</returns>
        public RenderIfBuilder RenderIf(bool condition, string format, params string[] values)
        {
            return new RenderIfBuilder(condition, format, values);
        }

        /// <summary>
        /// Renders only if value given value is not empty
        /// </summary>
        /// <param name="data">IF this data is empty then nothing renders</param>
        /// <returns>A RenderIfBuilder so that you may continue to build your conditional render statement with else etc.</returns>
        public RenderIfBuilder RenderIfNotEmpty(string data)
        {
            return string.IsNullOrEmpty(data) == false && data.Trim().Length > 0
                       ? new RenderIfBuilder(true, data)
                       : new RenderIfBuilder(false, data);
        }

        /// <summary>
        /// Renders only if value given value is not empty
        /// </summary>
        /// <param name="data">IF this data is empty then nothing renders</param>
        /// <param name="content">The content to render if the data is not empty</param>
        /// <returns>A RenderIfBuilder so that you may continue to build your conditional render statement with else etc.</returns>
        public RenderIfBuilder RenderIfNotEmpty(string data, string content)
        {
            return string.IsNullOrEmpty(data) == false && data.Trim().Length > 0
                       ? new RenderIfBuilder(true, content)
                       : new RenderIfBuilder(false, content);
        }

        /// <summary>
        /// Renders only if value given is not empty
        /// </summary>
        /// <param name="data">IF this data is empty then nothing renders</param>
        /// <param name="content">The content to render using String.Format if the data is not empty</param>
        /// <param name="params">The values to assign to the String.Format</param>
        /// <returns>A RenderIfBuilder so that you may continue to build your conditional render statement with else etc.</returns>
        public RenderIfBuilder RenderIfNotEmpty(string data, string content, params string[] @params)
        {
            return string.IsNullOrEmpty(data) == false && data.Trim().Length > 0
                       ? new RenderIfBuilder(true, content, @params)
                       : new RenderIfBuilder(false, content, @params);
        }

        public string SetFocusAfter(string selector, int millisseconds)
        {
            return SetFocusAfter(selector, millisseconds, true);
        }

        public string SetFocusAfter(string selector, int millisseconds, bool addScriptTag)
        {
            var code = string.Format("setTimeout('jQuery(\"{0}\").focus()', {1}); ", selector, millisseconds);
            return addScriptTag ? "<script type='text/javascript'>" + code + "</script>" 
                                : code;
        }

        /// <summary>
        /// Generates an HTML table from a given data table
        /// </summary>
        /// <param name="data">The data to ouput as the html table</param>
        /// <returns>HTML String</returns>
        public string GenerateHtmlTable(DataTable data)
        {
            var tb = new StringBuilder();
            tb.AppendLine("<table>");

            // Create the headers
            tb.AppendLine("<thead>");
            tb.AppendLine("<tr>");
            foreach (DataColumn col in data.Columns) {
                tb.AppendFormat("<th>{0}</th>{1}", col.ColumnName, "\r\n");
            }
            tb.AppendLine("</tr>");
            tb.AppendLine("</thead>");

            // Create the rows
            tb.AppendLine("<tbody>");
            foreach (DataRow row in data.Rows) {
                tb.AppendLine("<tr>");
                foreach (DataColumn col in data.Columns) {
                    tb.AppendLine("<td>");
                    if (row.IsNull(col) == false) {
                        tb.Append(HttpUtility.HtmlEncode(row[col].ToString()));
                    }
                    tb.AppendLine("</td>" + "\r\n");
                }
                tb.AppendLine("</tr>");
            }
            tb.AppendLine("</tbody>");
            tb.AppendLine("</table>");

            // Return the data
            return tb.ToString();
        }
        
        /// <summary>
        /// Creates a Link based date picker. It does this by creating three components
        /// 1. A link element
        /// 2. A hidden element carrying the date value with the format of the server
        /// 3. A script that changes the value of the hidden input and the link when a date is selected
        /// **The hidden element will always carry the USDate unless manually configured to do otherwise
        /// </summary>
        /// <param name="linkText">The text to display when no date is selected</param>
        /// <param name="title">The hover title</param>
        /// <param name="id">The id to assign to the link</param>
        /// <param name="value">The initial value</param>
        /// <param name="datePickerFormat">This is the date format used by the jQuery.DatePicker control</param>
        /// <param name="linkDateFormat">This will be the format of date when displayed as the link text. 
        /// this is used to format the value parameter. After that everytime you select a date, the datePickerFormat is used
        /// to assign it to the link text</param>
        /// <param name="linkClass">The class(es) if any to apply to the link</param>
        /// <param name="calContainerClass">The class(es) if any to apply to the div containing the calendar</param>
        /// <returns>An Html string with the Input, Link, DatePicker Div, and the script</returns>
        public string LinkDatePicker(string linkText, string title, string id, DateTime value, 
                                            string datePickerFormat, string linkDateFormat, 
                                            string linkClass, string calContainerClass)
        {
            var linkId = id + "_link";
            var calId = id + "_cal";
            var fieldId = id;
            var hiddenFieldValue = "";

            // If a default value was supplied then set the linkText to the value supplied 
            //  as well as the hidden field's value
            if (value != DateTime.MinValue)
            {
                linkText = value.ToString(linkDateFormat);
                hiddenFieldValue = value.ToString(CultureInfo.CreateSpecificCulture("en-US")
                                                             .DateTimeFormat.ShortDatePattern);
            }

            // Add the selecotr link
            var helper = new StringBuilder();
            helper.AppendLine(new TagBuilder("a").href(string.Format("javascript:jQuery('#{0}').show();void(0);", calId))
                                                 .InnerText(linkText).title(title).AddClass(linkClass).ID(linkId).ToString());
            // Add the div to contain the calendar
            helper.AppendLine("<div id='" + calId + "' style='display:none' class='" + calContainerClass + "'></div>");
            helper.AppendLine(Hidden(fieldId).value(hiddenFieldValue).ToString());
            helper.AppendLine("<script type='text/javascript'>");
            helper.AppendLine("     jQuery(function () {");
            helper.AppendLine("         jQuery('#" + calId + "').datepicker({");
            helper.AppendLine("             onSelect: function (dateText, inst) {");
            helper.AppendLine("                 jQuery('#" + fieldId + "').val(dateText);");
            helper.AppendLine("                 jQuery('#" + linkId + "').text(jQuery.datepicker.formatDate('" + datePickerFormat + "', new Date(dateText)));");
            helper.AppendLine("                 jQuery('#" + calId + "').hide();");
            helper.AppendLine("             }");
            helper.AppendLine("         });");
            helper.AppendLine("     });");
            helper.AppendLine("</script>");

            return helper.ToString();
        }


        
    }
    
}